{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Replication step 1 - Calibration\n",
    "\n",
    "This notebook produces calibrated steady states for the models in \"MPCs, MPEs and Multipliers: A Trilemma for New Keynesian Models\".\n",
    "\n",
    "Full notebook calibrates 60 HANK economies and can take 1-2 hours to run on a laptop. \n",
    "\n",
    "1. [Baseline](#baseline)\n",
    "2. [High EIS](#high-eis)\n",
    "3. [Low Frisch](#low-frisch)\n",
    "4. [High labor wedge](#high-wedge)\n",
    "5. [Progressive marginal taxation](#prog-tax)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Standard Python packages\n",
    "import numpy as np\n",
    "import copy\n",
    "\n",
    "# Models\n",
    "import sticky_price as sp\n",
    "import sticky_wage as sw\n",
    "\n",
    "# Save results?\n",
    "savedata = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='baseline'></a>\n",
    "## 1. Baseline calibration\n",
    "\n",
    "Summarized by Table 1 in the paper."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky price model\n",
    "Consider 11 economies that span the range between separable and GHH preferences in terms of consumption-labor complementarity index (CI). Specifically, let $\\alpha=0,0.1,\\dots,0.9,1.$ \n",
    "\n",
    "For each economy, we internally calibrate 7 parameters\n",
    "- patient discount factor (`betamax`)\n",
    "- impatient discount factor (`betamax - brange`)\n",
    "- curvature of felicity function (`sigma`)\n",
    "- disutility of labor (`vphi`)\n",
    "- aggregate labor productivity (`Z`)\n",
    "- standard deviation of income shocks (`sd_e`)\n",
    "- fixed cost of production (`F`)\n",
    "\n",
    "To hit 7 targets\n",
    "- asset market clearing `0=A-B-p` given a real interest rate `r`\n",
    "- average EIS\n",
    "- normalize aggregate hours `N=1`\n",
    "- normalize aggregate output `Y=1`\n",
    "- standard deviation of pre-tax labor income\n",
    "- value of firm equity\n",
    "- average MPC\n",
    "\n",
    "The calibration has two loops. The outer loop searches over `brange` to hit the MPC target. The inner loop searches over the other 6 variables to hit the other 6 targets. The reason for separating the two is that, given discrete time and a discretized income process, average MPC is discontinuous function of the discount factor. Therefore, in general, MPC targets are not possible to hit very precisely. In contrast, all other targets can (or must, in the case of market clearing) be hit with high precision.   \n",
    "\n",
    "To make the notebook run faster, we provide narrow interval for `brange`, so the solver converges in just a few steps. If you want to modify parameters, you have to allow for a wider interval (`bmin`, `bmax`) and more steps (`maxit`) in the outer loop.   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working on alpha = 0.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0545\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.1\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0435\n",
      "MPC= 0.250\n",
      "Working on alpha = 0.2\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.035500000000000004\n",
      "MPC= 0.251\n",
      "Starting inner loop for betarange = 0.035250000000000004\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.30000000000000004\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0315\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.03125\n",
      "MPC= 0.244\n",
      "Starting inner loop for betarange = 0.031375\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.0313125\n",
      "MPC= 0.244\n",
      "Starting inner loop for betarange = 0.031343750000000004\n",
      "MPC= 0.258\n",
      "Working on alpha = 0.4\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0285\n",
      "MPC= 0.266\n",
      "Starting inner loop for betarange = 0.02825\n",
      "MPC= 0.265\n",
      "Starting inner loop for betarange = 0.028125\n",
      "MPC= 0.250\n",
      "Working on alpha = 0.5\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0235\n",
      "MPC= 0.249\n",
      "Working on alpha = 0.6000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0205\n",
      "MPC= 0.249\n",
      "Working on alpha = 0.7000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0185\n",
      "MPC= 0.250\n",
      "Working on alpha = 0.8\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0175\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.9\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0165\n",
      "MPC= 0.249\n",
      "Starting inner loop for betarange = 0.01675\n",
      "MPC= 0.250\n",
      "Working on alpha = 1.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0165\n",
      "MPC= 0.247\n",
      "Starting inner loop for betarange = 0.01675\n",
      "MPC= 0.248\n",
      "Starting inner loop for betarange = 0.016875\n",
      "MPC= 0.249\n",
      "Starting inner loop for betarange = 0.0169375\n",
      "MPC= 0.249\n",
      "Starting inner loop for betarange = 0.01696875\n",
      "MPC= 0.249\n"
     ]
    }
   ],
   "source": [
    "alpha_vec = np.linspace(0, 1, num=11)\n",
    "bmin_vec = np.array([0.054, 0.043, 0.035, 0.031, 0.028, 0.023, 0.020, 0.018, 0.017, 0.016, 0.016])\n",
    "bmax_vec = bmin_vec + 0.001\n",
    "\n",
    "sp1 = {}\n",
    "for k, (alpha, bmin, bmax) in enumerate(zip(alpha_vec, bmin_vec, bmax_vec)): \n",
    "    print(f'Working on alpha = {alpha}')\n",
    "    print('----------------------------------------------------')\n",
    "    sp1[k] = sp.calibrate(alpha=alpha, bmin=bmin, bmax=bmax, nS=25, p=0.85*4, maxit=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky wage model\n",
    "There's a single calibration, with separable preferences. In this model, `EIS=1/sigma` and income inequality can be parameterized directly (since everybody works the same hours), which leaves 5 parameters to calibrate internally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting inner loop for betarange = 0.0235\n",
      "MPC= 0.249\n",
      "------------------------------------------\n",
      "Starting inner loop for betarange = 0.02375\n",
      "MPC= 0.250\n",
      "------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "sw1 = sw.calibrate(bmin=0.023, bmax=0.024, maxit=5, nS=25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "if savedata:\n",
    "    ss_baseline = {'sticky_price': sp1, 'sticky_wage': sw1}\n",
    "    np.save('import_export/calibration/sp_baseline.npy', ss_baseline)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='high-eis'></a>\n",
    "## 2. High EIS calibration\n",
    "\n",
    "Increase elasticity of intertemporal substitution from 0.5 to 1.\n",
    "\n",
    "**Note**: to accommodate this change, we have to change the calibration among some other dimension as well. The reason is that the sticky wage model would have too high MPC even in the absence of beta heterogeneity. One solution is to increase liquidity in the economy. Specifically, we target a higher equity price."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky price model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working on alpha = 0.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.011\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.1\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.009499999999999998\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.2\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.008\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.30000000000000004\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0075\n",
      "MPC= 0.255\n",
      "Starting inner loop for betarange = 0.0072499999999999995\n",
      "MPC= 0.240\n",
      "Starting inner loop for betarange = 0.007375\n",
      "MPC= 0.254\n",
      "Working on alpha = 0.4\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.006500000000000001\n",
      "MPC= 0.242\n",
      "Starting inner loop for betarange = 0.006750000000000001\n",
      "MPC= 0.244\n",
      "Starting inner loop for betarange = 0.006875000000000001\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.006812500000000001\n",
      "MPC= 0.257\n",
      "Starting inner loop for betarange = 0.006781250000000001\n",
      "MPC= 0.257\n",
      "Working on alpha = 0.5\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.006500000000000001\n",
      "MPC= 0.261\n",
      "Starting inner loop for betarange = 0.00625\n",
      "MPC= 0.259\n",
      "Starting inner loop for betarange = 0.006125\n",
      "MPC= 0.245\n",
      "Starting inner loop for betarange = 0.0061875\n",
      "MPC= 0.245\n",
      "Working on alpha = 0.6000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.006\n",
      "MPC= 0.262\n",
      "Starting inner loop for betarange = 0.00575\n",
      "MPC= 0.260\n",
      "Starting inner loop for betarange = 0.005625\n",
      "MPC= 0.245\n",
      "Working on alpha = 0.7000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0055\n",
      "MPC= 0.261\n",
      "Starting inner loop for betarange = 0.0052499999999999995\n",
      "MPC= 0.245\n",
      "Working on alpha = 0.8\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.004999999999999999\n",
      "MPC= 0.245\n",
      "Starting inner loop for betarange = 0.0052499999999999995\n",
      "MPC= 0.261\n",
      "Starting inner loop for betarange = 0.005124999999999999\n",
      "MPC= 0.260\n",
      "Starting inner loop for betarange = 0.005062499999999999\n",
      "MPC= 0.245\n",
      "Working on alpha = 0.9\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.004999999999999999\n",
      "MPC= 0.259\n",
      "Starting inner loop for betarange = 0.004749999999999999\n",
      "MPC= 0.243\n",
      "Starting inner loop for betarange = 0.004874999999999999\n",
      "MPC= 0.244\n",
      "Starting inner loop for betarange = 0.004937499999999999\n",
      "MPC= 0.244\n",
      "Starting inner loop for betarange = 0.004968749999999999\n",
      "MPC= 0.259\n",
      "Working on alpha = 1.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.004999999999999999\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.004749999999999999\n",
      "MPC= 0.241\n",
      "Starting inner loop for betarange = 0.004874999999999999\n",
      "MPC= 0.242\n",
      "Starting inner loop for betarange = 0.004937499999999999\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.004906249999999999\n",
      "MPC= 0.257\n"
     ]
    }
   ],
   "source": [
    "alpha_vec = np.linspace(0, 1, num=11)\n",
    "bmin_vec = np.array([0.0105, 0.009, 0.0075, 0.007, 0.006, 0.006, 0.0055, 0.005, 0.0045, 0.0045, 0.0045])\n",
    "bmax_vec = bmin_vec + 0.001\n",
    "\n",
    "sp2 = {}\n",
    "for k, (alpha, bmin, bmax) in enumerate(zip(alpha_vec, bmin_vec, bmax_vec)): \n",
    "    print(f'Working on alpha = {alpha}')\n",
    "    print('----------------------------------------------------')\n",
    "    sp2[k] = sp.calibrate(EIS_target=1.0, sigma_guess=1.0, p=1.1*4, alpha=alpha, bmin=bmin, bmax=bmax, nS=25, maxit=5,\n",
    "                          MPC_tol=0.005)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky wage model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting inner loop for betarange = 0.0025\n",
      "MPC= 0.248\n",
      "------------------------------------------\n",
      "Starting inner loop for betarange = 0.00375\n",
      "MPC= 0.252\n",
      "------------------------------------------\n",
      "Starting inner loop for betarange = 0.003125\n",
      "MPC= 0.250\n",
      "------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "sw2 = sw.calibrate(bmin=0.0, bmax=0.005, maxit=5, p=1.1*4, sigma=1.0, nS=25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "if savedata:\n",
    "    ss_higheis = {'sticky_price': sp2, 'sticky_wage': sw2}\n",
    "    np.save('import_export/calibration/sp_higheis.npy', ss_higheis)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='low-frisch'></a>\n",
    "## 3. Low Frisch calibration\n",
    "Decrease Frisch elasticity from 0.5 to 0.25. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky price model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working on alpha = 0.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.044000000000000004\n",
      "MPC= 0.261\n",
      "Starting inner loop for betarange = 0.03900000000000001\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.1\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0375\n",
      "MPC= 0.248\n",
      "Working on alpha = 0.2\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0375\n",
      "MPC= 0.259\n",
      "Starting inner loop for betarange = 0.0325\n",
      "MPC= 0.248\n",
      "Working on alpha = 0.30000000000000004\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.0375\n",
      "MPC= 0.285\n",
      "Starting inner loop for betarange = 0.0325\n",
      "MPC= 0.257\n",
      "Starting inner loop for betarange = 0.03\n",
      "MPC= 0.251\n",
      "Working on alpha = 0.4\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.03125\n",
      "MPC= 0.262\n",
      "Starting inner loop for betarange = 0.026250000000000002\n",
      "MPC= 0.249\n",
      "Working on alpha = 0.5\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.252\n",
      "Working on alpha = 0.6000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.258\n",
      "Starting inner loop for betarange = 0.02\n",
      "MPC= 0.243\n",
      "Starting inner loop for betarange = 0.0225\n",
      "MPC= 0.250\n",
      "Working on alpha = 0.7000000000000001\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.262\n",
      "Starting inner loop for betarange = 0.02\n",
      "MPC= 0.247\n",
      "Working on alpha = 0.8\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.265\n",
      "Starting inner loop for betarange = 0.02\n",
      "MPC= 0.250\n",
      "Working on alpha = 0.9\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.267\n",
      "Starting inner loop for betarange = 0.02\n",
      "MPC= 0.252\n",
      "Working on alpha = 1.0\n",
      "----------------------------------------------------\n",
      "Starting inner loop for betarange = 0.025\n",
      "MPC= 0.267\n",
      "Starting inner loop for betarange = 0.02\n",
      "MPC= 0.251\n"
     ]
    }
   ],
   "source": [
    "alpha_vec = np.linspace(0, 1, num=11)\n",
    "bmin_vec = np.array([0.034, 0.0275, 0.0275, 0.0275, 0.02125, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015])\n",
    "bmax_vec = bmin_vec + 0.02\n",
    "\n",
    "sp3 = {}\n",
    "for k, (alpha, bmin, bmax) in enumerate(zip(alpha_vec, bmin_vec, bmax_vec)): \n",
    "    print(f'Working on alpha = {alpha}')\n",
    "    print('----------------------------------------------------')\n",
    "    sp3[k] = sp.calibrate(nu=4.0, alpha=alpha, bmin=bmin, bmax=bmax, nS=25, maxit=10, MPC_tol=0.005)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky wage model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting inner loop for betarange = 0.0245\n",
      "MPC= 0.252\n",
      "------------------------------------------\n",
      "Starting inner loop for betarange = 0.02425\n",
      "MPC= 0.251\n",
      "------------------------------------------\n",
      "Starting inner loop for betarange = 0.024125\n",
      "MPC= 0.251\n",
      "------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "sw3 = sw.calibrate(nu=4, bmin=0.024, bmax=0.025, maxit=10, nS=25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "if savedata:\n",
    "    ss_lowfrisch = {'sticky_price': sp3, 'sticky_wage': sw3}\n",
    "    np.save('import_export/calibration/sp_lowfrisch.npy', ss_lowfrisch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='high-wedge'></a>\n",
    "## 4. High labor wedge calibration\n",
    "Increase markup from 7/6 to 1.5."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky price model\n",
    "Higher markup does not affect households at all (as long as the effect on liquidity is offset by higher fixed costs). Therefore, we can recycle the baseline calibration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "sp4 = copy.deepcopy(sp1)\n",
    "for k in range(11):\n",
    "    sp4[k]['mup'] = 1.5\n",
    "    sp4[k]['Z'] = sp4[k]['mup'] * (1 - sp4[k]['p'] * sp4[k]['r'])\n",
    "    sp4[k]['F'] = sp4[k]['Z'] - 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky wage model "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "sw4 = copy.deepcopy(sw1)\n",
    "sw4['mup'] = 1.5\n",
    "sw4['Z'] = sw4['mup'] * (1 - sw4['p'] * sw4['r'])\n",
    "sw4['F'] = sw4['Z'] - 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "if savedata:\n",
    "    ss_highwedge = {'sticky_price': sp4, 'sticky_wage': sw4}\n",
    "    np.save('import_export/calibration/sp_highwedge.npy', ss_highwedge)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='prog-tax'></a>\n",
    "## 5. High-income households pay for government spending\n",
    "Gov't spending above steady state is financed by labor tax on high-income households. (top 10 income gridpoints $\\sim$ top 15% of the income distribution)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky price model\n",
    "This does not affect the steady state at all."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "sp5 = copy.deepcopy(sp1)\n",
    "for k in range(11):\n",
    "    sp5[k]['tax_rule'] = np.concatenate((np.zeros(15), np.ones(10), np.zeros(15), np.ones(10)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sticky wage model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "sw5 = copy.deepcopy(sw1)\n",
    "sw5['tax_rule'] = np.concatenate((np.zeros(15), np.ones(10), np.zeros(15), np.ones(10)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "if savedata:\n",
    "    ss_progtax = {'sticky_price': sp5, 'sticky_wage': sw5}\n",
    "    np.save('import_export/calibration/sp_progtax.npy', ss_progtax)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
